﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;


namespace DualChannelProject
{
    class MatcherUtilities
    {
        
        public static Image<Rgb, Byte> WAffine(Image<Rgb, Byte> img, Matrix<float> AFFMatrix)
        {
            Image<Rgb, Byte> imgWAffine = img.WarpAffine<float>(AFFMatrix, INTER.CV_INTER_LINEAR, WARP.CV_WARP_DEFAULT, new Rgb(0, 0, 0));
            return imgWAffine;
        }

        
        public static PointF[] ZoomImgIn(PointF[] src, PointF[] dst, float ZoomValue)
        {
            if (ZoomValue < 0) ZoomValue = -ZoomValue;
            for (int i = 0; i < 3; i++)
            {   
                dst[i].X += src[i].X * ZoomValue;
                dst[i].Y += src[i].Y * ZoomValue;
            }

            return dst;
        }
        public static PointF[] ZoomImgOut(PointF[] src, PointF[] dst, float ZoomValue)
        {
            if (ZoomValue < 0) ZoomValue = -ZoomValue;
            for (int i = 0; i < 3; i++)
            {
                dst[i].X -= src[i].X * ZoomValue;
                dst[i].Y -= src[i].Y * ZoomValue;
            }

            return dst;
        }
        public static PointF[] ShearX(PointF[] src, PointF[] dst, float Sx)
        {
            if (Sx > 0) Sx = -Sx;
            PointF dif = new PointF(Sx, 0);
          

            for (int i = 0; i < 3; i++)
            {
                dst[i].X += src[i].Y * dif.X;// +src[i].X;
            }
            
            return dst;
        }
        public static PointF[] ShearX2(PointF[] src, PointF[] dst, float Sx)
        {
             if (Sx <0) Sx = -Sx;
            PointF dif = new PointF(Sx, 0);

            
            for (int i = 0; i < 3; i++)
            {
                dst[i].X += src[i].Y * dif.X;// +src[i].X;
            }

            return dst;
        }
        public static PointF[] ShearY(PointF[] src, PointF[] dst, float Sy)
        {
            if (Sy < 0) Sy = -Sy;
            PointF dif = new PointF(0, Sy);

            for (int i = 0; i < 3; i++)
            {
                dst[i].Y += src[i].X * dif.Y;//src[i].Y;
            }

            return dst;
        }
        public static PointF[] ShearY2(PointF[] src, PointF[] dst, float Sy)
        {
            if (Sy > 0) Sy = -Sy;
            PointF dif = new PointF(0, Sy);

            for (int i = 0; i < 3; i++)
            {
                dst[i].Y += src[i].X * dif.Y;//src[i].Y;
            }

            return dst;
        }
        public static PointF[] TranslatRight(PointF[] src, PointF[] dst, float Tx)
        {
            PointF difX=new PointF(Tx,0);
    
            for( int i=0;i<3;i++)
            {
                dst[i].X += (1 + difX.X);
                //dst[i].Y += difX.Y;
            }
            return dst;
        }
        public static PointF[] TranslatLeft(PointF[] src, PointF[] dst, float Tx)
        {
            PointF difX=new PointF(Tx,0);
    
            for( int i=0;i<3;i++)
            {
                dst[i].X -= (1 + difX.X);
               // dst[i].Y -=  difX.Y;
            }
            return dst;
        }

        public static PointF[]  TranslatUp(PointF[] src, PointF[] dst, float Ty)
        {
            PointF difY=new PointF(0,Ty);
   
            for( int i=0;i<3;i++)
            {
                //dst[i].X += (difY.X);
                dst[i].Y -= (1 + difY.Y);
            }
            return dst;   
        }
        public static PointF[] TranslatDown(PointF[] src, PointF[] dst, float Ty)
        {
            PointF difY = new PointF(0, Ty);

            for (int i = 0; i < 3; i++)
            {
                //dst[i].X += (difY.X);
                dst[i].Y += (1 + difY.Y);
            }
            return dst;
        }
      

      public static PointF[] ScallingX(PointF[] src, PointF[] dst, float Sx)
      {
          if (Sx > 0) Sx = -Sx;
          PointF dif = new PointF(Sx, 0);


          for (int i = 0; i < 3; i++)
          {
              dst[i].X += src[i].X * dif.X;// +src[i].X;
          }

          return dst;
      }
      public static PointF[] ScallingX2(PointF[] src, PointF[] dst, float Sx)
      {
          if (Sx < 0) Sx = -Sx;
          PointF dif = new PointF(Sx, 0);

          for (int i = 0; i < 3; i++)
          {
              dst[i].X += src[i].X * dif.X;// +src[i].X;
          }

          return dst;
      }
      public static PointF[] ScallingY(PointF[] src, PointF[] dst, float Sy)
      {
          if (Sy < 0) Sy = -Sy;
          PointF dif = new PointF(0, Sy);

          for (int i = 0; i < 3; i++)
          {
              dst[i].Y += src[i].Y * dif.Y;//src[i].Y;
          }

          return dst;
      }
      public static PointF[] ScallingY2(PointF[] src, PointF[] dst, float Sy)
      {
          if (Sy > 0) Sy = -Sy;
          PointF dif = new PointF(0, Sy);

          for (int i = 0; i < 3; i++)
          {
              dst[i].Y += src[i].Y * dif.Y;//src[i].Y;
          }

          return dst;
      }
      public static PointF[] Rotation(PointF[] src, PointF[] dst, float Rot, PointF Center,PointF CenterAf)
      {
          Center.X = (dst[0].X + dst[2].X) / 2;
          Center.Y = (dst[0].Y + dst[1].Y ) / 2;
                   

          double[] beta = new double[3];

          Matrix<float> ma = new Matrix<float>(2,3);
          //ma.Ptr = CvInvoke.cvGetAffineTransform(src, dst, ma);
          ma.Ptr = CvInvoke.cv2DRotationMatrix(CenterAf, Rot, 1, ma.Ptr);
          

          PointF[] ddd = new PointF[3]; 
          dst.CopyTo(ddd, 0);

          for (int i = 0; i < 3; i++)
          {
              dst[i].X = ddd[i].X * ma[0, 0] + ddd[i].Y * ma[0, 1] + ma[0, 2];
              dst[i].Y = ddd[i].X * ma[1, 0] + ddd[i].Y * ma[1, 1] + ma[1, 2];
          }
          return dst;
          
      }
    }   
}

